import React, { useEffect, useRef, useState } from 'react';
import { LabASR } from 'byted-ailab-speech-sdk';
import ReactMarkdown from 'react-markdown';
import { Avatar, Spin, Space } from 'antd';
import { LoadingOutlined, UserOutlined } from '@ant-design/icons';
import remarkGfm from 'remark-gfm';
import { buildFullUrl, getToken, isJsonString } from '../util/helps';
import { chatQuery } from '../api/chat';
import yggImg from '../assets/WechatIMG8.jpeg';
import classNames from 'classnames';
import DigitalHuman from './DigitalHuman';
import { createConversation } from '../api/chat';

const appid = '4607500527';

const tips = [
  '问题已收到',
  '意图识别中...',
  '意图识别完成，调用任务处理模块',
  '启动子任务智能体...',
  '信息匹配中...',
  '生成答案'
]

const VoiceChat = () => {
  const [header, setHeader] = useState('');
  const [copyStat, setCopyStat] = useState(false);
  const [messages, setMessages] = useState([
    // { from:'ai', text: '您好，我是原格格基层治理AI服务助手，很高兴为您服务' }
    // { from: 'user', text: '你好，你能为我做什么？' },
    // { from: 'ai', text: '您好，我是原格格基层治理AI服务助手，可以为您提供以下服务：查询学龄儿童信息、高龄津贴领取人员信息、残疾人相关信息（包括重度残疾人和困难残疾人）以及各类人员数量统计。如果您有具体需求，请告诉我，我会尽力为您提供准确的信息。' }
  ]);
  const [curReply, setCurReply] = useState('spin');
  const [volume, setVolume] = useState(0);
  const [tipsIdx, setTipsIdx] = useState(0);
  const timerRef = useRef(null);
  const voices = useRef([]);
  const recordStopping = useRef(true);
  const [recordStoppingCopy, setRecordStoppingCopy] = useState(true)
  const endLock = useRef(false);
  const activeStatus = useRef(false);
  const [endLockCopy, setEndLockCopy] = useState(false)
  const switchTimer = useRef(null);
  const messagesEndRef = useRef(null);
  const readerRef = useRef(null);
  const ctrRef = useRef(null);
  const tokenRef = useRef('');
  const [asrClient] = useState(
    LabASR({
      onMessage: async (text, fullData) => {
        try {
          asrTextRef.current = ''
          let textArr = fullData.result?.utterances;
          textArr?.forEach(i => {
            asrTextRef.current += i.text
          })

          // if (textArr && textArr[textArr.length - 1].definite === false && textArr[textArr.length - 1].start_time === -1 && textArr[textArr.length - 1].text === '' && endLock.current === false) {
          // handle voice message...
          // }
        } catch (error) {
          setCopyStat(false)
          let aiText = '您好，网络超时，暂时无法回答您的问题'
          setMessages(prev => [...prev, { from: 'ai', text: aiText }]);
          playHuman();
          chatCopy(aiText);
          console.log('error', error)
        }
      },
      onStart() {
        setHeader('正在录音');
      },
      onClose() {
        setHeader('录音结束');
      },
    })
  );

  const digitalHumanRef = useRef(null);
  const [prologue] = useState(['您好，我想找工作', '你好，我想租一个两居室', '李江沟村的五老人员有哪些？']);
  const prologueTopRef = useRef(null);
  const prologueBottomRef = useRef(null);
  const [appConversationID, setAppConversationID] = useState('')
  const appConversationIDRef = useRef('')
  const asrTextRef = useRef('')

  const chatCopy = (content) => {
    if (endLock.current === false) {
      return;
    }
    const regex = /[\(（]注：([^）\)]+)[\)）]/g;
    const aiRegex = /(ai)/ig;
    const tableRegex = /\|.*\|[\r\n]\|[-: |]+\|[\r\n](?:\|.*\|[\r\n])*/g;
    content += '\n';
    content = content.replaceAll(tableRegex, '表格中的数据供您参考。');
    content = content.replaceAll(aiRegex, '诶哀');
    content = content.replaceAll(regex, '$1' + '。');
    content = content.replace(/^#{1,6}\s*/gm, '');
    content = content.replace(/[*_]{1,3}([^*_]+)[*_]{1,3}/g, '$1');
    content = content.replace(/`([^`]+)`/g, '$1');
    content = content.replace(/^[-*+] /gm, '');
    const utterance = new SpeechSynthesisUtterance(content);
    utterance.lang = 'zh-CN';
    utterance.pitch = 1.2;      // 音调（0~2），默认1
    utterance.rate = 1;       // 语速（0.1~10），默认1
    utterance.onend = () => {
      stopHuman();
      console.log('播报完成 ✅');
      endLock.current = false;
      setEndLockCopy(false)
      // startASR(); // 播报完继续开启识别
    };
    utterance.onerror = (e) => {
      console.log('播报失败 ❌', e);
    }
    if (voices.current.length === 0) {
      console.log('语音列表加载失败');
    }
    // 选择名字中可能是“男声”的语音（如包含 "Male", "男", "Ting", "Yun"）
    const maleVoice = voices.current.find(voice =>
      voice.lang === 'zh-CN' &&
      /Li-Mu/i.test(voice.name)
    );
    if (maleVoice) {
      utterance.voice = maleVoice;
    } else {
      console.warn('没有找到明确的中文男声，将使用默认中文语音');
    }
    speechSynthesis.speak(utterance);
    // speakWithSplit(content);
  }

  const startASR = async () => {
    recordStopping.current = false;
    setRecordStoppingCopy(false);
    const auth = {};
    // const accessKey = 'Nmtj3o5a5mQSZgkuOcUZ3VQthE6tcR1G'
    // const token = await getToken(appid, accessKey);
    // const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiNDYwNzUwMDUyNyJdLCJleHAiOjE3NDc5NDY2MDJ9.GKZNp_glTn8GzG_hZYIczyXYlYWlJ5kEdvIPCN1RotE';
    if (tokenRef.current === '') {
      tokenRef.current = await handleToken();
    }
    auth.api_resource_id = 'volc.bigasr.sauc.duration';
    auth.api_app_key = appid;
    auth.api_access_key = `Jwt; ${tokenRef.current}`;
    const fullUrl = buildFullUrl(`wss://openspeech.bytedance.com/api/v3/sauc/bigmodel`, auth);
    const params = {
      url: fullUrl,
      config: {
        user: {
          uid: 'ygg_robot_zyq',
        },
        audio: {
          format: 'pcm',
          rate: 16000,
          bits: 16,
          channel: 1,
        },
        request: {
          model_name: 'bigmodel',
          show_utterances: true,
          enable_vad: true,
          vad_segment_duration: 3000,
          enable_punc: true
        },
      },
    };
    asrClient.connect(params);
    await asrClient?.startRecord({}, async (recordResult) => {
      // 音频采集数据，可用于音频可视化需要
      const rawData = await recordResult.arrayBuffer();
      console.warn('rawData:', rawData);
    });
  };
  const stopASR = () => {
    // 正在关闭中...
    if (recordStopping.current) {
      return;
    }
    recordStopping.current = true;
    setRecordStoppingCopy(true);
    asrClient.stopRecord();
    if (asrTextRef.current) {
      handleSendMessage(asrTextRef.current);
    }
  };

  const handleToken = async () => {
    const accessKey = 'Nmtj3o5a5mQSZgkuOcUZ3VQthE6tcR1G';
    const token = await getToken(appid, accessKey);
    tokenRef.current = token;
  }

  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  };

  const playHuman = () => {
    digitalHumanRef.current.play();
  };

  const stopHuman = () => {
    digitalHumanRef.current.stop();
  };

  const handleSendMessage = async (msg) => {
    if (endLock.current) return;
    try {
      endLock.current = true;
      setEndLockCopy(true);
      setCopyStat(true);
      stopASR();
      console.log('发送的消息：', msg);
      if (!switchTimer.current) {
        switchTimer.current = setInterval(() => {
          setTipsIdx(val => {
            if (val === 5) {
              return val
            } else {
              return val + 1
            }
          })
        }, 2000);
      }
      setMessages(prev => [...prev, { from: 'user', text: msg }]);
      let answerObj = {
        from: 'ai',
        text: 'spin'
      };
      ctrRef.current = new AbortController();
      const signal = ctrRef.current.signal;
      const res = await chatQuery({
        signal,
        AppConversationID: appConversationID,
        Query: msg,
        ResponseMode: 'streaming', // streaming/blocking
        UserID: 'paulwing',
        QueryExtends: {}
      });
      if (res?.ok) {
        readerRef.current = res.body.getReader();
        const decoder = new TextDecoder('utf-8');
        let streamRes = await readerRef.current.read();
        while (!streamRes.done) {
          const chunk = decoder.decode(streamRes.value, { stream: true });
          console.log('收到一段数据:', chunk);
          let regex = /data:\s*(\{.*?\})\s*$/gm;
          // let replyArr = chunk.split(/event:text\ndata:data: |\ndata:\ndata:\n\n/g);
          let replyArr = [...chunk.matchAll(regex)].map(m => m[1]);
          // console.log(replyArr)
          if (replyArr?.length > 0) {
            replyArr = replyArr.forEach(item => {
              if (isJsonString(item)) {
                if (JSON.parse(item)?.event === 'message_start') {
                  setMessages(prev => [...prev, answerObj]);
                  // setCopyStat(true);
                }
                if (JSON.parse(item)?.event === 'message_start'
                  || JSON.parse(item)?.event === 'agent_take_over'
                  || JSON.parse(item)?.event === 'agent_jump'
                  || JSON.parse(item)?.event === 'agent_thought'
                  || JSON.parse(item)?.event === 'agent_thought_end'
                  || JSON.parse(item)?.event === 'message_output_start'
                  || JSON.parse(item)?.event === 'knowledge_retrieve'
                  || JSON.parse(item)?.event === 'knowledge_retrieve_end'
                  || JSON.parse(item)?.event === 'terminology_retrieve'
                  || JSON.parse(item)?.event === 'terminology_retrieve_end') {
                  setHeader(JSON.parse(item)?.event === 'message_start'
                    ? '工具链触发...'
                    : JSON.parse(item)?.event === 'agent_take_over'
                      ? '智能体接管中...'
                      : JSON.parse(item)?.event === 'agent_jump'
                        ? '智能体跳转...'
                        : JSON.parse(item)?.event === 'agent_thought'
                          ? '深度思考中...'
                          : JSON.parse(item)?.event === 'agent_thought_end'
                            ? '调用工具中...'
                            : JSON.parse(item)?.event === 'terminology_retrieve'
                              ? '术语匹配中...'
                              : JSON.parse(item)?.event === 'terminology_retrieve_end'
                                ? '术语匹配结束...'
                                : JSON.parse(item)?.event === 'knowledge_retrieve'
                                  ? '知识库信息检索中...'
                                  : JSON.parse(item)?.event === 'knowledge_retrieve_end'
                                    ? '知识库信息检索结束...'
                                    : '消息流输出开始...');
                }
                if (JSON.parse(item)?.event === 'message_output_start') {
                  clearInterval(switchTimer.current)
                  switchTimer.current = null
                  setTipsIdx(0)
                  setHeader('消息流输出开始...')
                }
                if (answerObj.text === 'spin' && JSON.parse(item)?.event === 'message') {
                  setCurReply(''); // 触发react重新渲染
                  answerObj.text = '';
                }
                answerObj.text += JSON.parse(item)?.answer || '';
                setCurReply(answerObj.text); // 触发react重新渲染
              }
            });
          } else {
            console.log(replyArr);
          }
          console.log(answerObj.text);
          streamRes = await readerRef.current.read();
        }
        if (streamRes.done) {
          console.log('✅ 流读取完毕');
          // markdown表格与表格后的内容切割开
          const tableRegex = /\|.*\|[\r\n]\|[-: |]+\|[\r\n](?:\|.*\|[\r\n])*/g;
          answerObj.text = answerObj.text.replaceAll(tableRegex, match => match + '\n');
          setCurReply(answerObj.text); // 触发react重新渲染
        }
      } else {
        throw new Error(`请求失败：${res.status}:${res.statusText}`);
      }
      setCopyStat(false);

      if (!endLock.current) return
      playHuman();
      // 播报
      chatCopy(answerObj.text);
    }
    catch (error) {
      setCopyStat(false);
      let aiText = '您好，网络超时，暂时无法回答您的问题';
      setMessages(prev => [...prev, { from: 'ai', text: aiText }]);
      playHuman();
      chatCopy(aiText);
      console.log('error', error);
    }
  }

  const activeSpeechForAndroid = () => {
    const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
    if (isTouchDevice) {
      console.log('activeSpeechForAndroid');
      endLock.current = true;
      chatCopy('');
    }
  }

  useEffect(() => {
    const el = prologueTopRef.current;
    if (!el) return;

    const handleWheel = (e) => {
      e.preventDefault();
      el.scrollLeft += e.deltaY;
    };

    el.addEventListener("wheel", handleWheel, { passive: false });

    return () => {
      el.removeEventListener("wheel", handleWheel);
    };

  }, [messages]);

  useEffect(() => {
    if (switchTimer.current !== null) {
      setHeader(tips[tipsIdx])
    }
  }, [tipsIdx])

  useEffect(() => {
    scrollToBottom();
  }, [messages, curReply]);

  useEffect(() => {
    if (!copyStat) {
      setHeader('')
      clearInterval(timerRef.current);
    }
  }, [copyStat]);

  useEffect(() => {
    (async function () {
      speechSynthesis.onvoiceschanged = async () => {
        voices.current = speechSynthesis.getVoices();
        await handleToken();
        // startASR();
      }
      let res = await createConversation({
        UserID: 'paulwing'
      })
      if (res?.status === 200) {
        const val = res.data.Conversation.AppConversationID
        console.log('AppConversationID:', val)
        setAppConversationID(val);
        appConversationIDRef.current = val
      }
    })()
  }, [])

  // useEffect(() => {
  //   const el = prologueBottomRef.current;
  //   if (!el) return;

  //   const handleWheel = (e) => {
  //     e.preventDefault();
  //     el.scrollLeft += e.deltaY;
  //   };

  //   el.addEventListener("wheel", handleWheel, { passive: false });

  //   return () => {
  //     el.removeEventListener("wheel", handleWheel);
  //   };

  // }, [messages]);

  return (
    <div className="w-full h-full flex flex-col items-center overflow-auto">
      <div className='w-[80%] flex items-center my-4'>
        <div className='shrink-0'>
          <Avatar size={46} src={<img src={yggImg} alt="avatar" />} />
        </div>
        <div className="ml-2 text-xl font-bold text-black">朝阳教委AI服务助手</div>
      </div>

      <Spin wrapperClassName="voice-chat-spin w-[80%] h-full mb-5 overflow-auto" spinning={!appConversationID} tip="加载中..." >
        <div className="h-full p-4 flex flex-col rounded-3xl mb-5 overflow-auto relative" style={{ backgroundImage: 'linear-gradient(360deg,#e2e8ff 0,#f5f7fd 100%)' }}>
          <div className='flex-1 flex overflow-auto'>
            <div className="left-video w-[280px] shrink-0 flex items-center overflow-hidden">
              <DigitalHuman ref={digitalHumanRef}></DigitalHuman>
            </div>
            <div className="flex-1 overflow-auto flex flex-col">
              {
                messages.length ? null : <div className="mb-10 max-w-[90%] mx-auto">
                  <div className="font-bold text-2xl mb-2">Hi，您好！</div>
                  <div className="text-gray-500 text-lg mb-5">我是朝阳教委AI服务助手，很高兴为您服务，有什么问题都可以咨询我，我将努力为您解答。</div>
                  <div className='text-left text-gray-700 mb-2'>你可以试着发送问题</div>
                  <div className='overflow-auto whitespace-nowrap scrollbar justify-center flex' ref={prologueTopRef}>
                    <div className="flex space-x-5 max-w-[100%]">
                      {
                        prologue.map((item, i) => {
                          return (
                            <div key={`pt-${i}`} className='flex flex-col bg-white rounded-xl px-5 py-3 cursor-pointer hover:opacity-80' onClick={() => handleSendMessage(item)}>
                              <div className='font-bold mb-2 text-left'>{item}</div>
                              <div className='inline-flex self-end text-sm items-center bg-indigo-50 rounded-2xl px-2 py-1 text-blue-500'>
                                试一试
                                <i className='iconfont icon-a-RightArrow text-sm'></i>
                              </div>
                            </div>
                          );
                        })
                      }
                    </div>
                  </div>
                </div>
              }
              <div className="space-y-6 flex-1 overflow-auto scrollbar rounded-xl">
                {messages.map((msg, i) => (
                  <div key={`message-${i}`} className={classNames("flex", msg.from === 'user' ? 'justify-end' : 'justify-start')}>
                    {
                      msg.from === 'ai' ?
                        <div className='shrink-0'>
                          <Avatar size={48} src={<img src={yggImg} alt="avatar" />} />
                        </div>
                        : <></>
                    }
                    <div className={classNames("rounded-xl p-4 text-2xl md-wrapper overflow-auto", msg.from === 'user' ? 'bg-blue-500 text-white text-left rounded-br-none' : 'bg-white text-left text-stone-800 max-w-[1200px] ml-[12px]')}>
                      {
                        msg.from === 'ai' && copyStat && i === messages.length - 1 ? <div className='flex items-center text-stone-500 mb-2'><Spin className='text-2xl mr-[12px]' />
                          <span className='shine-text'>{header}</span>
                        </div> : <></>
                      }
                      {
                        msg.from === 'ai' && msg.text === 'spin' ? '' : <ReactMarkdown
                          remarkPlugins={[remarkGfm]}
                          breaks={true}
                        // components={{
                        //   table: ({ _, ...props }) => (
                        //     <table {...props} className="max-w-full border-collapse border border-gray-300 border-collapse break-keep whitespace-nowrap" />
                        //   ),
                        //   th: ({ _, ...props }) => (
                        //     <th {...props} className="border border-gray-300 px-4 py-2 text-left font-semibold bg-gray-100" />
                        //   ),
                        //   td: ({ _, ...props }) => (
                        //     <td {...props} className="border border-gray-300 px-4 py-2" />
                        //   )
                        // }}
                        >{msg.text}</ReactMarkdown>
                      }
                    </div>
                  </div>
                ))}
                <div ref={messagesEndRef} />
              </div>
              <div className="flex items-center space-x-4 justify-center relative">
                {
                  copyStat ?
                    <button
                      onClick={() => {
                        try {
                          // stopASR();
                          if (readerRef.current) {
                            console.error('cancel')
                            readerRef.current?.cancel();
                            readerRef.current = null;
                          }
                          if (ctrRef.current) {
                            ctrRef.current?.abort();
                            ctrRef.current = null;
                          }
                          endLock.current = false;
                          setEndLockCopy(false);
                          window.speechSynthesis.cancel();
                          // stopASR();
                          let tempMsg = messages;
                          let len = tempMsg.length;
                          if (len > 0 && tempMsg[len - 1].text === 'spin') {
                            tempMsg[len - 1].text = '用户已取消';
                          }
                          setMessages(tempMsg);
                          stopHuman();
                        } catch (error) {
                          throw new Error(error);
                        }
                      }}
                      className="px-4 py-2 bg-blue-400 text-white rounded-full min-w-[180px] cursor-not-allowed"
                    >
                      <i className="iconfont icon-dui"></i>  信息已收到，请稍候...
                    </button> :
                    <>
                      {!recordStopping.current ? <button
                        onClick={() => {
                          stopASR();
                          // stopHuman();
                        }}
                        className="px-4 py-2 bg-red-500 text-white rounded-full min-w-[180px] flex justify-center"
                      >
                        <i className="iconfont icon-zanting text-xl mr-2"></i> 正在接收语音
                      </button> :
                        <button
                          onClick={() => {
                            if (!activeStatus.current) {
                              activeSpeechForAndroid();
                              activeStatus.current = true;
                            }
                            if (!endLock.current) {
                              console.log('start');
                              startASR();
                            } else {
                              endLock.current = false;
                              setEndLockCopy(false)
                              window.speechSynthesis.cancel();
                              setVolume(prev => prev + 1);
                              stopHuman();
                            }
                          }}
                          className={`px-4 py-2 bg-green-400 text-white rounded-full min-w-[180px] flex justify-center`}
                        >
                          {
                            endLock.current ?
                              <div className='flex items-center justify-center'><i className="iconfont icon-bobao text-xl mr-2"></i>播报中...</div>
                              :
                              <div className='flex items-center justify-center'><i className="iconfont icon-shiwu-maikefeng text-xl mr-2"></i>点击开始对话</div>
                          }
                        </button>}
                    </>
                }
              </div>
            </div>
          </div>
        </div>
      </Spin>

    </div>
  );
};

export default VoiceChat;
